home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / svgakt50.zip / SRC / SVGAKIT / GETOPT.C < prev    next >
C/C++ Source or Header  |  1993-10-21  |  11KB  |  336 lines

  1. /****************************************************************************
  2. *
  3. *                   Copyright (C) 1993 SciTech Software.
  4. *                            All rights reserved.
  5. *
  6. * Filename:        $RCSfile: getopt.c $
  7. * Version:        $Revision: 1.5 $
  8. *
  9. * Language:        ANSI C
  10. * Environment:    any
  11. *
  12. * Description:    This module contains code to parse the command line,
  13. *                extracting options and parameters in standard System V
  14. *                style.
  15. *
  16. * $Id: getopt.c 1.5 1991/12/31 19:39:55 kjb Exp $
  17. *
  18. ****************************************************************************/
  19.  
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23. #include "debug.h"
  24. #include "getopt.h"
  25.  
  26. /*------------------------- Global variables ------------------------------*/
  27.  
  28. int        nextargv    =    1;            /* Index into argv array            */
  29. char    *nextchar    =    NULL;        /* Pointer to next character        */
  30.  
  31. /*-------------------------- Implementation -------------------------------*/
  32.  
  33. #ifdef    __MSDOS__
  34. #define    IS_SWITCH_CHAR(c)        (c == '-') || (c == '/')
  35. #define    IS_NOT_SWITCH_CHAR(c)    (c != '-') && (c != '/')
  36. #else
  37. #define    IS_SWITCH_CHAR(c)        (c == '-')
  38. #define    IS_NOT_SWITCH_CHAR(c)    (c != '-')
  39. #endif
  40.  
  41. PUBLIC int getopt(int argc,char **argv,char *format,char **argument)
  42. /****************************************************************************
  43. *
  44. * Function:        getopt
  45. * Parameters:    argc        -    Value passed to program through argc
  46. *                                variable in the function main.
  47. *                argv        -     Pointer to the argv array that is passed to
  48. *                                the program in function main.
  49. *                format        -    A string representing the expected format
  50. *                                of the command line options that need to be
  51. *                                parsed.
  52. *                argument    -     Pointer to optional argument on command
  53. *                                line.
  54. *
  55. * Returns:        Character code representing the next option parsed from the
  56. *                command line by getopt. Returns ALLDONE (-1) when there are
  57. *                no more parameters to be parsed on the command line,
  58. *                PARAMETER (-2) when the argument being parsed is a
  59. *                parameter and not an option switch and lastly INVALID (-3)
  60. *                if an error occured while parsing the command line.
  61. *
  62. * Description:    Function to parse the command line option switches in
  63. *                UNIX System V style. When getopt is called, it returns the
  64. *                character code of the next valid option that is parsed from
  65. *                the command line as specified by the Format string. The
  66. *                format string should be in the following form:
  67. *
  68. *                        "abcd:e:f:"
  69. *
  70. *                where a,b and c represent single switch style options and
  71. *                the character code returned by getopt is the only value
  72. *                returned. Also d, e and f represent options that expect
  73. *                arguments immediately after them on the command line. The
  74. *                argument that follows the option on the command line is
  75. *                returned via a reference in the pointer argument. Thus
  76. *                a valid command line for this format string might be:
  77. *
  78. *                    myprogram -adlines /b /f format infile outfile
  79. *
  80. *                where a and b will be returned as single character options
  81. *                with no argument, while d is returned with the argument
  82. *                lines and f is returned with the argument format. Note that
  83. *                either UNIX style or MS-DOS command switches may be used
  84. *                interchangeably under MSDOS, but under UNIX only the UNIX
  85. *                style switches are supported.
  86. *
  87. *                When getopt returns with PARAMETER (we attempted to parse
  88. *                a paramter, not an option), the global variable NextArgv
  89. *                will hold an index in the argv array to the argument on the
  90. *                command line AFTER the options, ie in the above example the
  91. *                string 'infile'. If the parameter is successfully used,
  92. *                NextArgv should be incremented and getopt can be called
  93. *                again to parse any more options. Thus you can also have
  94. *                options interspersed throught the command line. eg:
  95. *
  96. *                    myprogram -adlines infile /b outfile /f format
  97. *
  98. *                can be made to be a valid form of the above command line.
  99. *
  100. ****************************************************************************/
  101. {
  102.     char    ch;
  103.     char    *formatchar;
  104.  
  105.     if (argc > nextargv) {
  106.         if (nextchar == NULL) {
  107.             nextchar = argv[nextargv];        /* Index next argument         */
  108.             if(nextchar == NULL) {
  109.                 nextargv++;
  110.                 return ALLDONE;                /* No more options             */
  111.                 }
  112.             if(IS_NOT_SWITCH_CHAR(*nextchar)) {
  113.                 nextchar = NULL;
  114.                 return PARAMETER;            /* We have a parameter         */
  115.                 }
  116.             nextchar++;                    /* Move past switch operator    */
  117.             if(IS_SWITCH_CHAR(*nextchar)) {
  118.                 nextchar = NULL;
  119.                 return INVALID;                /* Ignore rest of line         */
  120.                 }
  121.             }
  122.  
  123.         if ((ch = *(nextchar++)) == 0) {
  124.             nextchar = NULL;
  125.             return INVALID;                    /* No options on line         */
  126.             }
  127.  
  128.         if (ch == ':' ||  (formatchar = strchr(format, ch)) == NULL)
  129.             return INVALID;
  130.  
  131.         if (*(++formatchar) == ':') {    /* Expect an argument after option */
  132.             nextargv++;
  133.             if (*nextchar == 0) {
  134.                 if (argc <= nextargv)
  135.                     return INVALID;
  136.                 nextchar = argv[nextargv++];
  137.                 }
  138.             *argument = nextchar;
  139.             nextchar = NULL;
  140.             }
  141.         else {                        /* We have a switch style option    */
  142.             if (*nextchar == 0) {
  143.                 nextargv++;
  144.                 nextchar = NULL;
  145.             }
  146.             *argument = NULL;
  147.             }
  148.         return ch;                    /* return the option specifier         */
  149.         }
  150.     nextchar = NULL;
  151.     nextargv++;
  152.     return ALLDONE;                    /* no arguments on command line     */
  153. }
  154.  
  155. PRIVATE int parse_option(Option *optarr,char *argument)
  156. /****************************************************************************
  157. *
  158. * Function:        parse_option
  159. * Parameters:    optarr        - Description for the option we are parsing
  160. *                argument    - String to parse
  161. * Returns:        INVALID on error, ALLDONE on success.
  162. *
  163. * Description:    Parses the argument string depending on the type of argument
  164. *                that is expected, filling in the argument for that option.
  165. *                Note that to parse a string, we simply return a pointer
  166. *                to argument.
  167. *
  168. ****************************************************************************/
  169. {
  170.     int        num_read = 0;
  171.  
  172.     switch ((int)(optarr->type)) {
  173.         case OPT_INTEGER:
  174.             num_read = sscanf(argument,"%d",optarr->arg);
  175.             break;
  176.         case OPT_HEX:
  177.             num_read = sscanf(argument,"%x",optarr->arg);
  178.             break;
  179.         case OPT_OCTAL:
  180.             num_read = sscanf(argument,"%o",optarr->arg);
  181.             break;
  182.         case OPT_UNSIGNED:
  183.             num_read = sscanf(argument,"%u",optarr->arg);
  184.             break;
  185.         case OPT_LINTEGER:
  186.             num_read = sscanf(argument,"%ld",optarr->arg);
  187.             break;
  188.         case OPT_LHEX:
  189.             num_read = sscanf(argument,"%lx",optarr->arg);
  190.             break;
  191.         case OPT_LOCTAL:
  192.             num_read = sscanf(argument,"%lo",optarr->arg);
  193.             break;
  194.         case OPT_LUNSIGNED:
  195.             num_read = sscanf(argument,"%lu",optarr->arg);
  196.             break;
  197.         case OPT_FLOAT:
  198.             num_read = sscanf(argument,"%f",optarr->arg);
  199.             break;
  200.         case OPT_DOUBLE:
  201.             num_read = sscanf(argument,"%lf",optarr->arg);
  202.             break;
  203.         case OPT_LDOUBLE:
  204.             num_read = sscanf(argument,"%Lf",optarr->arg);
  205.             break;
  206.         case OPT_STRING:
  207.             num_read = 1;            /* This always works    */
  208.             *((char**)optarr->arg) = argument;
  209.             break;
  210.         default:
  211.             return INVALID;
  212.         }
  213.  
  214.     if (num_read == 0)
  215.         return INVALID;
  216.     else
  217.         return ALLDONE;
  218. }
  219.  
  220. PUBLIC int getargs(int argc,char *argv[],int num_opt,Option optarr[],
  221.                    int (*do_param)(char *param,int num))
  222. /****************************************************************************
  223. *
  224. * Function:        getargs
  225. * Parameters:    argc        - Number of arguments on command line
  226. *                argv        - Array of command line arguments
  227. *                num_opt        - Number of options in option array
  228. *                optarr        - Array to specify how to parse the command line
  229. *                do_param    - Routine to handle a command line parameter
  230. * Returns:        ALLDONE, INVALID or HELP
  231. *
  232. * Description:    Function to parse the command line according to a table of
  233. *                options. This routine calls getopt above to parse each
  234. *                individual option and attempts to parse each option into
  235. *                a variable of the specified type. The routine can parse
  236. *                integers and long integers in either decimal, octal,
  237. *                hexadecimal notation, unsigned integers and unsigned longs,
  238. *                strings and option switches. Option switches are simply
  239. *                boolean variables that get turned on if the switch was
  240. *                parsed.
  241. *
  242. *                Parameters are extracted from the command line by calling
  243. *                a user supplied routine do_param() to handle each parameter
  244. *                as it is encountered. The routine do_param() should accept
  245. *                a pointer to the parameter on the command line and an
  246. *                integer representing how many parameters have been
  247. *                encountered (ie: 1 if this is the first parameter, 10 if
  248. *                it is the 10th etc), and return ALLDONE upon successfully
  249. *                parsing it or INVALID if the parameter was invalid.
  250. *
  251. *                We return either ALLDONE if all the options were
  252. *                successfully parsed, INVALID if an invalid option was
  253. *                encountered or HELP if any of -h, -H or -? were present
  254. *                on the command line.
  255. *
  256. ****************************************************************************/
  257. {
  258.     int        i,opt;
  259.     char    *argument;
  260.     int        param_num = 1;
  261.     char    cmdstr[MAXARG*2 + 4];
  262.  
  263.     /* Build the command string from the array of options    */
  264.  
  265.     strcpy(cmdstr,"hH?");
  266.     for (i = 0,opt = 3; i < num_opt; i++,opt++) {
  267.         cmdstr[opt] = optarr[i].opt;
  268.         if (optarr[i].type != OPT_SWITCH) {
  269.             cmdstr[++opt] = ':';
  270.             }
  271.         }
  272.     cmdstr[opt] = '\0';
  273.  
  274.     while (true) {
  275.         opt = getopt(argc,argv,cmdstr,&argument);
  276.         switch (opt) {
  277.             case 'H':
  278.             case 'h':
  279.             case '?':
  280.                 return HELP;
  281.             case ALLDONE:
  282.                 return ALLDONE;
  283.             case INVALID:
  284.                 return INVALID;
  285.             case PARAMETER:
  286.                 if (do_param == NULL)
  287.                     return INVALID;
  288.                 if (do_param(argv[nextargv],param_num) == INVALID)
  289.                     return INVALID;
  290.                 nextargv++;
  291.                 param_num++;
  292.                 break;
  293.             default:
  294.  
  295.                 /* Search for the option in the option array. We are
  296.                  * guaranteed to find it.
  297.                  */
  298.  
  299.                 for (i = 0; i < num_opt; i++) {
  300.                     if (optarr[i].opt == opt)
  301.                         break;
  302.                     }
  303.                 if (optarr[i].type == OPT_SWITCH)
  304.                     *((bool*)optarr[i].arg) = true;
  305.                 else {
  306.                     if (parse_option(&optarr[i],argument) == INVALID)
  307.                         return INVALID;
  308.                     }
  309.                 break;
  310.             }
  311.         }
  312. }
  313.  
  314. PUBLIC void print_desc(int num_opt,Option optarr[])
  315. /****************************************************************************
  316. *
  317. * Function:        print_desc
  318. * Parameters:    num_opt    - Number of options in the table
  319. *                optarr    - Table of option descriptions
  320. *
  321. * Description:    Prints the description of each option in a standard format
  322. *                to the standard output device. The description for each
  323. *                option is obtained from the table of options.
  324. *
  325. ****************************************************************************/
  326. {
  327.     int        i;
  328.  
  329.     for (i = 0; i < num_opt; i++) {
  330.         if (optarr[i].type == OPT_SWITCH)
  331.             printf("  -%c       %s\n",optarr[i].opt,optarr[i].desc);
  332.         else
  333.             printf("  -%c<arg>  %s\n",optarr[i].opt,optarr[i].desc);
  334.         }
  335. }
  336.